=begin rdoc
Periodic is used for event field that have a wrapping counter.
In the analysis you want to disinguish them, thus needing to assign them
to a larger not wrapping value. Up to some granularity of course.

Author::    Matthias Woehrle  (mailto:matthias.woehrle@tik.ee.ethz.ch)
Copyright:: Copyright (c) 2008 ETH Zurich
License::   

TODO:

MISSING:


=end

# Periodic implements a totally ordered integer representation of a
# wrapping integer in a range R
# Intialized by its range any new value can be computed in the correct order
# based on a heuristic implemented in the order function
class Periodic

  WRAP_RANGE = 0.5

  #Intialize a perdioc variable with a range. The range determines where the periodic wraps and is
  #used to internally compute a totally ordered integer.
  def initialize(range)
    @last = Hash.new
    @current_prefix = Hash.new
    #todo - this works for ranges only at the moment
    min = range.first
    max = range.last
    @offset = min
    @period = max - min + 1
    @of_detected = Hash.new
    self
  end
  
  #Put the current reading from a wrapping integer (a periodic) into a long integer for ordering.
  def order(current,nodeid)
    @last[nodeid] || @last[nodeid] = 0
    @current_prefix[nodeid] || @current_prefix[nodeid] = 0
    @of_detected[nodeid] || @of_detected[nodeid] = 0
    high_tide = (1-WRAP_RANGE) * @period
    low_tide  = (WRAP_RANGE) * @period
    current -= @offset
    if @last[nodeid] % @period  > high_tide and current % @period  < low_tide and @of_detected[nodeid] == 0
      @of_detected[nodeid] = 1
    elsif @of_detected[nodeid]==1 and current % @period  < high_tide and current % @period  > low_tide
      @of_detected[nodeid] = 0
      @current_prefix[nodeid] +=1
    end
    @last[nodeid] = current

    current =  current + @period * @of_detected[nodeid] if current < low_tide
    current += @current_prefix[nodeid] * @period #increment if overflow_detected
    
    
    current
  end
end